/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.inferred.freebuilder.processor.util.testing;
import static com.google.common.collect.Iterables.getOnlyElement;
import static javax.lang.model.util.ElementFilter.methodsIn;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import com.google.common.reflect.TypeToken;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.NestingKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
/** Tests for {@link Model}. */
@RunWith(JUnit4.class)
public class ModelTest {
@Rule public final ExpectedException thrown = ExpectedException.none();
private Model model;
@Before
public void setup() {
model = Model.create();
}
@Test
public void typeUtils() {
PrimitiveType booleanType = model.typeUtils().getPrimitiveType(TypeKind.BOOLEAN);
assertEquals("boolean", booleanType.toString());
}
@Test
public void elementUtils() {
String oneHundredAndOne = model.elementUtils().getConstantExpression(101L);
assertEquals("101L", oneHundredAndOne);
}
@Test
public void environment() {
assertSame(model.elementUtils(), model.environment().getElementUtils());
}
@Test
public void newElementWithMarker() {
TypeElement type = (TypeElement) model.newElementWithMarker(
"package foo.bar;",
"public class MyType {",
" ---> public class MyInnerType {",
" public void doNothing() { }",
" }",
"}");
assertEquals(ElementKind.CLASS, type.getKind());
assertEquals(NestingKind.MEMBER, type.getNestingKind());
assertEquals("MyInnerType", type.getSimpleName().toString());
assertEquals("foo.bar.MyType.MyInnerType", type.toString());
assertEquals("doNothing",
getOnlyElement(methodsIn(type.getEnclosedElements())).getSimpleName().toString());
}
@Test
public void newElementWithMarker_noElementIdentified() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Code must identify the element to be returned using '--->'");
model.newElementWithMarker(
"package foo.bar;",
"public class MyType {",
" public class MyInnerType {",
" public void doNothing() { }",
" }",
"}");
}
@Test
public void newElementAnnotatedWith() {
TypeElement type = (TypeElement) model.newElementAnnotatedWith(
Deprecated.class,
"package foo.bar;",
"public class MyType {",
" @Deprecated public class MyInnerType {",
" public void doNothing() { }",
" }",
"}");
assertEquals(ElementKind.CLASS, type.getKind());
assertEquals(NestingKind.MEMBER, type.getNestingKind());
assertEquals("MyInnerType", type.getSimpleName().toString());
assertEquals("foo.bar.MyType.MyInnerType", type.toString());
assertEquals("doNothing",
getOnlyElement(methodsIn(type.getEnclosedElements())).getSimpleName().toString());
}
@Test
public void newElementAnnotatedWith_noElementIdentified() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("no annotated element");
model.newElementAnnotatedWith(
Deprecated.class,
"package foo.bar;",
"public class MyType {",
" public class MyInnerType {",
" public void doNothing() { }",
" }",
"}");
}
@Test
public void newElementAnnotatedWith_twoElementsIdentified() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Multiple elements annotated with @java.lang.Deprecated found");
model.newElementAnnotatedWith(
Deprecated.class,
"package foo.bar;",
"public class MyType {",
" @Deprecated public class MyInnerType {",
" @Deprecated public void doNothing() { }",
" }",
"}");
}
@Test
public void newElementAnnotatedWith_compilationError() {
thrown.expect(CompilationException.class);
model.newElementAnnotatedWith(
Deprecated.class,
"package foo.bar;",
"public class MyType {",
" public class MyInnerType {",
" public void doNothing() {",
" }",
"}");
}
@Test
public void newType_class() {
TypeElement type = model.newType(
"package foo.bar;",
"public class MyType {",
" public void doNothing() { }",
"}");
assertEquals(ElementKind.CLASS, type.getKind());
assertEquals(NestingKind.TOP_LEVEL, type.getNestingKind());
assertEquals("MyType", type.getSimpleName().toString());
assertEquals("foo.bar.MyType", type.toString());
assertEquals("doNothing",
getOnlyElement(methodsIn(type.getEnclosedElements())).getSimpleName().toString());
}
@Test
public void newType_interface() {
TypeElement type = model.newType(
"package foo.bar;",
"public interface MyType {",
" public void doNothing();",
"}");
assertEquals(ElementKind.INTERFACE, type.getKind());
assertEquals(NestingKind.TOP_LEVEL, type.getNestingKind());
assertEquals("MyType", type.getSimpleName().toString());
assertEquals("foo.bar.MyType", type.toString());
assertEquals("doNothing",
getOnlyElement(methodsIn(type.getEnclosedElements())).getSimpleName().toString());
}
@Test
public void newType_enum() {
TypeElement type = model.newType(
"package foo.bar;",
"public enum MyType { A, B; }");
assertEquals(ElementKind.ENUM, type.getKind());
assertEquals(NestingKind.TOP_LEVEL, type.getNestingKind());
assertEquals("MyType", type.getSimpleName().toString());
assertEquals("foo.bar.MyType", type.toString());
}
@Test
public void newType_annotation() {
TypeElement type = model.newType(
"package foo.bar;",
"public @interface MyType {",
" String param();",
"}");
assertEquals(ElementKind.ANNOTATION_TYPE, type.getKind());
assertEquals(NestingKind.TOP_LEVEL, type.getNestingKind());
assertEquals("MyType", type.getSimpleName().toString());
assertEquals("foo.bar.MyType", type.toString());
assertEquals("param",
getOnlyElement(methodsIn(type.getEnclosedElements())).getSimpleName().toString());
}
@Test
public void typeMirror_string_nonGenericType() {
TypeMirror t1 = model.typeMirror("String");
assertEquals("java.lang.String", t1.toString());
TypeMirror t2 = model.typeMirror("String");
assertEquals(t1, t2);
}
@Test
public void typeMirror_string_genericType() {
TypeMirror t1 = model.typeMirror("java.util.List<Integer>");
assertEquals("java.util.List<java.lang.Integer>", t1.toString());
TypeMirror t2 = model.typeMirror("java.util.List<Integer>");
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_string_arrayOfGenericsType() {
TypeMirror t1 = model.typeMirror("java.util.List<String>[]");
assertEquals("java.util.List<java.lang.String>[]", t1.toString());
TypeMirror t2 = model.typeMirror("java.util.List<String>[]");
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_string_genericOfArraysType() {
TypeMirror t1 = model.typeMirror("java.util.List<String[]>");
assertEquals("java.util.List<java.lang.String[]>", t1.toString());
TypeMirror t2 = model.typeMirror("java.util.List<String[]>");
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_string_nestedGenericType() {
TypeMirror t1 = model.typeMirror("java.util.Map<String,java.util.List<Integer>>");
assertEquals(
"java.util.Map<java.lang.String,java.util.List<java.lang.Integer>>", t1.toString());
TypeMirror t2 = model.typeMirror("java.util.Map<String,java.util.List<Integer>>");
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_string_argumentSubstitution() {
TypeMirror t1 = model.typeMirror("java.util.Map<Integer, String>");
assertEquals("java.util.Map<java.lang.Integer,java.lang.String>", t1.toString());
TypeMirror t2 = model.typeMirror(
"java.util.Map<%1, %2>", model.typeMirror("Integer"), model.typeMirror("String"));
assertEquals("java.util.Map<java.lang.Integer,java.lang.String>", t2.toString());
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_string_rawTypeSubstitution() {
TypeMirror t = model.typeMirror(
"%1<%2>", model.typeMirror("java.util.List"), model.typeMirror("Integer"));
assertEquals("java.util.List<java.lang.Integer>", t.toString());
}
@Test
public void typeMirror_string_rawTypeSubstitutionError() {
TypeMirror stringList = model.typeMirror("java.util.List<String>");
TypeMirror integer = model.typeMirror("Integer");
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage(
"Expected raw type, got 'java.util.List<java.lang.String>'");
model.typeMirror("%1<%2>", stringList, integer);
}
@Test
public void typeMirror_string_wrongNumberOfGenericParameters() {
TypeMirror stringList = model.typeMirror("java.util.List<String>");
TypeMirror integer = model.typeMirror("Integer");
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Incorrect number of arguments for java.util.List (expected 1, got 2)");
model.typeMirror("java.util.List<%1, %2>", stringList, integer);
}
@Test
public void typeMirror_string_illegalSyntax() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid type string");
model.typeMirror("java.util.List<String><String>");
}
@Test
public void typeMirror_string_illegalSyntax2() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid type string");
model.typeMirror("java.util.List, java.util.List");
}
@Test
public void typeMirror_string_illegalSyntax3() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid type string");
model.typeMirror("java.util.List[]<String>");
}
@Test
public void typeMirror_string_illegalSyntax4() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid type string");
model.typeMirror("java.util.List[][]");
}
@Test
public void typeMirror_class_void() {
TypeMirror t1 = model.typeMirror(void.class);
assertEquals("void", t1.toString());
TypeMirror t2 = model.typeMirror(void.class);
assertEquals(t1, t2);
}
@Test
public void typeMirror_class_primitiveType() {
TypeMirror t1 = model.typeMirror(int.class);
assertEquals("int", t1.toString());
TypeMirror t2 = model.typeMirror(int.class);
assertEquals(t1, t2);
}
@Test
public void typeMirror_class_primitiveArray() {
TypeMirror t1 = model.typeMirror(int[].class);
assertEquals("int[]", t1.toString());
TypeMirror t2 = model.typeMirror(int[].class);
assertEquals(t1, t2);
}
@Test
public void typeMirror_class_nonGenericType() {
TypeMirror t1 = model.typeMirror(String.class);
assertEquals("java.lang.String", t1.toString());
TypeMirror t2 = model.typeMirror(String.class);
assertEquals(t1, t2);
}
@Test
public void typeMirror_class_nonGenericArray() {
TypeMirror t1 = model.typeMirror(String[].class);
assertEquals("java.lang.String[]", t1.toString());
TypeMirror t2 = model.typeMirror(String[].class);
assertEquals(t1, t2);
}
@Test
public void typeMirror_class_compilationBetweenInstances() {
TypeMirror t1 = model.typeMirror("java.lang.String");
TypeMirror t2 = model.typeMirror(String.class);
assertEquals(t1, t2);
}
@Test
public void typeMirror_class_genericType() {
TypeMirror t1 = model.typeMirror(List.class);
assertEquals("java.util.List", t1.toString());
TypeMirror t2 = model.typeMirror(List.class);
assertEquals(t1, t2);
}
@Test
public void typeMirror_class_genericArray() {
TypeMirror t1 = model.typeMirror(List[].class);
assertEquals("java.util.List[]", t1.toString());
TypeMirror t2 = model.typeMirror(List[].class);
assertEquals(t1, t2);
}
@Test
public void typeMirror_typeToken_nonGenericType() {
TypeMirror t1 = model.typeMirror(new TypeToken<String>() {});
assertEquals("java.lang.String", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<String>() {});
assertEquals(t1, t2);
}
@Test
public void typeMirror_typeToken_genericType() {
TypeMirror t1 = model.typeMirror(new TypeToken<List<Integer>>() {});
assertEquals("java.util.List<java.lang.Integer>", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<List<Integer>>() {});
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@SuppressWarnings("rawtypes")
@Test
public void typeMirror_typeToken_rawType() {
TypeMirror t1 = model.typeMirror(new TypeToken<List>() {});
assertEquals("java.util.List", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<List>() {});
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_typeToken_wildcard() {
TypeMirror t1 = model.typeMirror(new TypeToken<List<?>>() {});
assertEquals("java.util.List<?>", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<List<?>>() {});
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_typeToken_wildcardBoundedAboveType() {
TypeMirror t1 = model.typeMirror(new TypeToken<List<? super Number>>() {});
assertEquals("java.util.List<? super java.lang.Number>", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<List<? super Number>>() {});
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_typeToken_wildcardBoundedBelow() {
TypeMirror t1 = model.typeMirror(new TypeToken<List<? extends Number>>() {});
assertEquals("java.util.List<? extends java.lang.Number>", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<List<? extends Number>>() {});
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_typeToken_arrayOfGenericsType() {
TypeMirror t1 = model.typeMirror(new TypeToken<List<String>[]>() {});
assertEquals("java.util.List<java.lang.String>[]", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<List<String>[]>() {});
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_typeToken_genericOfArraysType() {
TypeMirror t1 = model.typeMirror(new TypeToken<List<String[]>>() {});
assertEquals("java.util.List<java.lang.String[]>", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<List<String[]>>() {});
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirror_typeToken_nestedGenericType() {
TypeMirror t1 = model.typeMirror(new TypeToken<Map<String, List<Integer>>>() {});
assertEquals(
"java.util.Map<java.lang.String,java.util.List<java.lang.Integer>>", t1.toString());
TypeMirror t2 = model.typeMirror(new TypeToken<Map<String, List<Integer>>>() {});
assertTrue("Same type", model.typeUtils().isSameType(t1, t2));
}
@Test
public void typeMirrorEqualsMethodReturnType() {
ExecutableElement method = (ExecutableElement) model.newElementWithMarker(
"package example.com;",
"interface Foo {",
" ---> String method();",
"}");
TypeMirror stringType = model.typeMirror("String");
assertTrue("Same type", model.typeUtils().isSameType(stringType, method.getReturnType()));
}
@After
public void teardown() {
model.destroy();
}
}